import os
import sys
import time
from datetime import datetime, timedelta
import logging

from sc_engine import parse_config, get_transport_from_config

from sc_engine.messaging import ApplicationMessageBus
from sc_engine.messaging import MainMessageBus

def import_app_module(app_name):
    app_module_prefix = 'sc_engine.apps'
    app_module_suffix = 'app'
    module_name = '%s.%s.%s' % (app_module_prefix, app_name, app_module_suffix)

    return __import__(module_name, fromlist=['app'])

class Main(object):
    def __init__(self, configs, transport):
        self.root_config = configs['root']
        self.configs = configs
        self.logger = logging.getLogger('main')

        self.transport = transport
        self.bus = MainMessageBus('main', transport)

    def add_app_old(self, app_name, builder):
        config = self.configs.get(app_name, {})
        subscriptions = builder(app_name, self.root_config, config)
        amb = ApplicationMessageBus(app_name, subscriptions)
        self.bus.add_app(app_name, amb, subscriptions)

    def add_app(self, app_name):
        config = self.configs.get(app_name, {})
        module = import_app_module(app_name)
        try:
            subscriptions = module.make_app(app_name, self.root_config, config)
        except AttributeError as e:
            err_msg = 'Module %s does not have make_app function' % module
            raise AttributeError(err_msg)
        amb = ApplicationMessageBus(app_name, subscriptions)
        self.bus.add_app(app_name, amb, subscriptions)

    def run(self):
        try:
            while True:
                self.bus.run()
        finally:
            try:
                self.bus.close()
            except BaseException as e:
                self.logger.exception("Exception when trying to close bus.")

if __name__ == '__main__':
    if len(sys.argv) < 2:
        raise SystemExitError("Must supply configuration file")

    config_filename = sys.argv[1]
    if not os.path.exists(config_filename):
        message = "Config file %s does not exist" % config_filename
        raise SystemExitError(message)

    configs = parse_config(config_filename)

    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)
    error_console = logging.StreamHandler()
    error_console.level = logging.ERROR
    logger.addHandler(error_console)

    logger = logging.getLogger("messages")
    console = logging.StreamHandler()
    logger.setLevel(logging.DEBUG)
    logger.addHandler(console)

    transport = get_transport_from_config(configs['root'])

    main = Main(configs, transport)

    # System
    #main.add_app('system.heartbeat')

    # Data
    main.add_app('aliasautogen')
    main.add_app('data.player')
    main.add_app('data.map')
    main.add_app('data.commentary')
    main.add_app('data.league_stage')

    main.add_app('unknown_data')
    main.add_app('forced_data')
    main.add_app('manual_youtube_link_converter')

    main.add_app('video_game_linking')
    main.add_app('match_game_id')

    # Fetch
    main.add_app('fetch.player')
    main.add_app('fetch.map')
    main.add_app('fetch.youtube')
    main.add_app('fetch.proleague_schedule')

    # parse
    main.add_app('parse.youtube')
    main.add_app('parse.proleague')

    # Web interface
    main.add_app('web.site_interface')
    main.add_app('web.console')
    main.add_app('web.map_image_upload')

    # Transfer

    main.run()
